#ifndef __CLOCK_HAL_H__
#define __CLOCK_HAL_H__
#include "A_Config.h"

//LGFX屏幕定义（注释看不懂）
class LGFX : public lgfx::LGFX_Device
{
public:
    // lgfx::Panel_ILI9341 _panel_instance;
    lgfx::Panel_ST7789 _panel_instance;
    lgfx::Bus_Parallel8 _bus_instance; // 8ビットパラレルバスのインスタンス (ESP32のみ)

public:
    LGFX(void)
    {
        {                                      // バス制御の設定を行います。
            auto cfg = _bus_instance.config(); // バス設定用の構造体を取得します。

            cfg.port = 0;              // 使用するI2Sポートを選択 (0 or 1) (ESP32のI2S LCDモードを使用します)
            cfg.freq_write = 20000000; // 送信クロック (最大20MHz, 80MHzを整数で割った値に丸められます)
            cfg.pin_wr = LCD_WR;       // WR を接続しているピン番号
            cfg.pin_rd = LCD_RD;       // RD を接続しているピン番号
            cfg.pin_rs = LCD_DC;       // RS(D/C)を接続しているピン番号

            cfg.pin_d0 = LCD_D0;
            cfg.pin_d1 = LCD_D1;
            cfg.pin_d2 = LCD_D2;
            cfg.pin_d3 = LCD_D3;
            cfg.pin_d4 = LCD_D4;
            cfg.pin_d5 = LCD_D5;
            cfg.pin_d6 = LCD_D6;
            cfg.pin_d7 = LCD_D7;

            _bus_instance.config(cfg);              // 設定値をバスに反映します。
            _panel_instance.setBus(&_bus_instance); // バスをパネルにセットします。
        }

        {                                        // 表示パネル制御の設定を行います。
            auto cfg = _panel_instance.config(); // 表示パネル設定用の構造体を取得します。

            cfg.pin_cs = -1;   // CS要拉低
            cfg.pin_rst = -1;  // RST和开发板RST相连
            cfg.pin_busy = -1; // BUSYが接続されているピン番号 (-1 = disable)

            // ※ 以下の設定値はパネル毎に一般的な初期値が設定されていますので、不明な項目はコメントアウトして試してみてください。

            cfg.offset_rotation = 1; // 回転方向の値のオフセット 0~7 (4~7は上下反転)
            cfg.readable = true;     // データ読出しが可能な場合 trueに設定
            cfg.invert = true;       // パネルの明暗が反転してしまう場合 trueに設定
            cfg.rgb_order = false;   // パネルの赤と青が入れ替わってしまう場合 trueに設定
            cfg.dlen_16bit = false;  // データ長を16bit単位で送信するパネルの場合 trueに設定
            cfg.bus_shared = false;  // SDカードとバスを共有している場合 trueに設定(drawJpgFile等でバス制御を行います)

            _panel_instance.config(cfg);
        }

        setPanel(&_panel_instance); // 使用するパネルをセットします。
    }
};

class ClockHAL
{
public:
    LGFX display;
    GT911 touch = GT911();
    #ifndef SD_IS_SDMMC
    SPIClass SDSPI = SPIClass(FSPI);
    #endif
    DS3231 rtc;
    AXP20X_Class axp;
    WiFiUDP Udp;
    SemaphoreHandle_t wiremutex;
    // SemaphoreHandle_t SPILock;
    SemaphoreHandle_t screenMutex;
    TaskHandle_t handleScreenUpdate;

    bool axpShortPress = false;
    bool axpLongPress = false;
    uint8_t Brightness = CONFIG_DEFAULT_BRIGHTNESS;
    volatile uint32_t release_time = 0;
    uint16_t autoSleepTime = AUTO_SLEEP_TIME_DEFAULT;
    volatile bool DoNotSleep = false; //禁止进入任何睡眠模式
    volatile bool DoNotSleepWhenUSB = true;   //是否在USB插入时保持唤醒
    volatile bool RTCInterrupted = false;
    volatile bool canDeepSleep = false;          //是否允许深度睡眠(1/2)，如果现在在时钟界面则允许。暂时禁止睡眠模式应置位DoNotSleep
    volatile bool canDeepSleepFromAlarm = false; //是否允许深度睡眠(2/2)，如果今天没有闹钟则允许。暂时禁止睡眠模式应置位DoNotSleep
    bool SDMounted = false;
    bool USBConnected = false;
    /**
     * @brief 复位触摸屏并初始化
    */
    void resetTouch();
    /**
     * @brief 使触摸屏进入休眠模式
    */
    void touchSleep();
    /**
     * @brief 初始化主板
     *
     */
    void initHardware();

    /**
     * @brief 更新硬件
     *
     */
    void update();

    /**
     * @brief 挂载TF卡
     *
     * @return true 挂载成功
     * @return false 挂载失败
     */
    bool mountSD();

    /**
     * @brief 卸载TF卡
     *
     */
    void unmountSD();

    void setupMSC(void);
    
    void displayOff(void);
    void displayOn(void);
    void setBrightness(uint8_t b);
    void lightSleep();
    void deepSleep();
    void rtcOffsetSecond(int8_t seconds);
    bool NTPSync();
    /**
     * @brief 校准触摸屏
     * 
     */
    void calibrateTouch();
private:
    void pre_sleep();
    void post_sleep();
    void setMediaPresent(bool isPresent);
};

extern ClockHAL hal;
#define LOCKLV() xSemaphoreTake(hal.screenMutex, portMAX_DELAY)
#define UNLOCKLV() xSemaphoreGive(hal.screenMutex)
#endif